package com.tinyshardingjdbc.tinyshardingjdbc.shardingasync.core;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.tinyshardingjdbc.tinyshardingjdbc.shardingasync.PageUtils;
import com.tinyshardingjdbc.tinyshardingjdbc.shardingasync.TinyShardingAsyncService;
import com.tinyshardingjdbc.tinyshardingjdbc.shardingasync.annotaion.TinyShardingJdbcVo;
import com.tinyshardingjdbc.tinyshardingjdbc.shardingasync.tool.HashTableName;
import org.apache.ibatis.plugin.Invocation;

import java.util.*;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;


public class HashProcessor implements TypeProcessor {


    @Override
    public List<String> getTableName(String tableStart, String tableEndDate, String tablePrefix, String fileValue, TinyShardingJdbcVo tinyShardingJdbcVo, Invocation invocation) {
        List<String> responseDTO = PageUtils.getTableNameHash(tinyShardingJdbcVo.getHashCount(), tablePrefix);
        /**
         * 存在关键字,只使用当前的表
         *
         * */
        if (!StringUtils.isBlank(fileValue)) {
            List<String> list = new ArrayList<>();
            list.add(tablePrefix + "_" + HashTableName.getTableNameprefix(fileValue, tinyShardingJdbcVo.getHashCount()));
            return list;
        }
        return responseDTO;
    }


    @Override
    public String getTableNameSuffix(String fileValue, TinyShardingJdbcVo tinyShardingJdbcVo, Invocation invocation) {
        return HashTableName.getTableNameprefix(fileValue, tinyShardingJdbcVo.getHashCount());
    }

    @Override
    public Object orderByProcessor(TinyShardingAsyncService shardingAsyncService, HashMap<String, Long> totalCountMap, List<String> table, String tablePrefix, String doDataSql, IPage<?> page, long totalCount) {
        List<Future<Object>> futureList = new ArrayList<>();
        for (String tableName : table) {
              String optSql = doDataSql.split("LIMIT")[0];
              optSql = optSql.replace(tablePrefix, tableName);
              Future<Object> asyncQueryPage = shardingAsyncService.asyncQueryPage(optSql);
              futureList.add(asyncQueryPage);
        }
        List<Map<String,Object>> entityList = new ArrayList<>();
        for (Future<Object> future : futureList) {
            try {
                List<Map<String,Object>> asyncQueryPageList = (  List<Map<String,Object>>) future.get(120, TimeUnit.SECONDS);
                for (Map<String,Object> os : asyncQueryPageList) {
                    entityList.add(os);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        /**
         * 未测试
         *
         * */
        String orderByKey=doDataSql.split("ORDER BY")[1].split(" ")[0].trim();
        if(doDataSql.toUpperCase().contains("ORDER BY")){
            entityList.sort(new Comparator<Map<String, Object>>() {
                @Override
                public int compare(Map<String, Object> o1, Map<String, Object> o2) {

                    if(doDataSql.toUpperCase().contains("DESC")){
                       if(!o1.containsKey(orderByKey)){
                           return 0;
                       }
                       if(!o2.containsKey(orderByKey)){
                           return 0;
                       }
                       return String.valueOf(o1.get(orderByKey)).compareTo(String.valueOf(o2.get(orderByKey)));
                   }else {
                       if(!o1.containsKey(orderByKey)){
                           return 1;
                       }
                       if(!o2.containsKey(orderByKey)){
                           return 1;
                       }
                       return String.valueOf(o2.get(orderByKey)).compareTo(String.valueOf(o1.get(orderByKey)));

                   }

                }
            });

        }


        return entityList;
    }
}
